#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "cluster.h"
#include "XgmmlCreator.h"


void addVertex(Network* net, char* verName);
void printDegree(Network* net, int id);
void addEdge(Network* net, int firstID, int secondID, double weight);
void idByName(Network* net, char* name);
void print(Network* net);
void quit(Network* net);


int main(int argc, char **argv);

/* user input handlers */
int extract_bounds_from_argv(char **argv, int *lb, int *ub, int *true_ub);
int handle_user_input(int arg_count, char** argv);
int build_network(Network *net);

/*Parsing mechanism*/
int number_of_parameters(char *input);
char* get_next_parameter(char *input, char* parameter);
int get_id(Network* net, char* name);

/* Input check */
int check_only_whitespace(Network* net, char *input);
int whitespace_shift(char *input);
int char_to_int(Network* net, char* number, int op);
double char_to_double(Network* net, char* number);
int str_vs_int(char* str, int num);

/* secure programming */
int sec_print(Network* net, char* str);

/* CPLEX memory handlers */
int create_objective_array(int number_of_clusters, double **obj_p);
int allocation_verifier(int* array);
int solve_k_cluster_problem(int number_of_clusters);
int fill_in_constraint_1(int number_of_clusters, int *constraint_id_p, edge_iterator *edge_iter_p, int *matind, double *matval, int *matbeg, double *rhs, char *sense);
int fill_in_constraint_2(int number_of_clusters, int *constraint_id_p, edge_iterator *edge_iter_p, int *matind, double *matval, int *matbeg, double *rhs, char *sense);
int fill_in_constraint_3(int number_of_clusters, int *constraint_id_p, edge_iterator *edge_iter_p, int *matind, double *matval, int *matbeg, double *rhs, char *sense);
int fill_in_constraint_4(int number_of_clusters, int *constraint_id_p, edge_iterator *edge_iter_p, int *matind, double *matval, int *matbeg, double *rhs, char *sense);

/* Output creators functions */
int create_results_file(double *scores, int lw_bound, int up_bound);
void assign_solution_values(double *solution_array, int num_of_variables, int num_of_clusters);
double cluster_score(int cluster_ID);
void average_weight_calculator(double *average_values);

/* Diameter & BFS functions */
int lsp_via_BFS(Vertex *source, int cluster_size);
int find_diameter(int cluster_id, int cluster_size);

/* Exit logic, memory cleaners & handlers */
void int_free_and_null (int **ptr);
void char_free_and_null (char **ptr);
void double_free_and_null (double **ptr);
int int_allocation_verifier(int* ptr);
int char_allocation_verifier(char* ptr);
int double_allocation_verifier(double* ptr);
void free_null_constraint_memory(double *obj,char *sense, double *rhs, int *matbeg, int *matcnt,
int *matind, double *matval, int *indices, char *ctype, double *lp, double *up, double *x, char *probname);

/* Cluster handlers & sort functions*/
int sort_clusters_by_size(int *array_of_clusters, int *array_of_cluster_sizes, int num_of_clusters);
int compare(const void * a, const void * b);
void cluster_sizes(int *array_of_cluster_sizes, int num_of_clusters);
void prepare_cluster_arrays(int *array_of_clusters, int *array_of_cluster_sizes, int num_of_clusters);


/* XGMML interface*/
/* xgmml Network creators/initializers*/
int Create_Network_Edges_Data_Stractures(Edge** networkEdges, int *NetEdgesSize);
int CreateNetwork_Vertices_Data_Stractures(Vertex** networkVertices, int *NetVerSize);
int Create_ClusterSet_Data_Stracture(ClusterSet** currentSet, Cluster** tCluster, int i );
Cluster* GetClusterById(int clusterId, int k);
int create_five_best_clusters(int num_of_clusters);
int IsContainsValue(int value, int* numbers, int numbersSize);
int GetClusterEdgesCount(int clusterId);
double GetClusterSumOfWeights(int clusterId);
Cluster* GetClusterById(int clusterId, int k);
int GetCrossClustersEdgesCount(int* topClusterIds, int size);




